package ascensor;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.TooManyListenersException;

//import ascensor.TwoWaySerialComm.SerialEventHandler;

public class ComunicacionSerie
{

	public ComunicacionSerie() // este es el constructor!
	{
		//super();
	}

	private OutputStream outputStream;
	private SerialPort puertoSerie = null;
	private CommPortIdentifier identificadorDePuerto;
	private InputStream in;
	private SerialPort puertoCerrar;

	// private byte[] readBuffer = new byte[400];
	private int[] BufferLectura = new int[400];
	private int PuertosDetectados = 0; // almaceno los puertos detectados
	public boolean DatosRecibidos = false;

	int len = 0;
	int largoborrar = 0;

	// Constructores y destructores
	/*
	 * Metodos: QueDevuelve nombreDeFuncion (tipoDeParametro parametro1,
	 * tipoDeParametro parametro2, ...)
	 * 
	 * SerialPort Abrirpuerto( )
	 * 
	 * //
	 * ------------------------------------------------------------------------
	 * ----------------------------------------------------- //
	 */
	/**
	 * 
	 * @param nombreDePuerto
	 * @param RatioBaudios
	 * @param Bitsdatos
	 * @param Bitsparada
	 * @param Paridad
	 * @return
	 * @return
	 * @throws Exception
	 * 
	 *             Parametros a pasar a la funcion, todos del tipo String Puerto
	 *             a abrir : nombreDePuerto BauRate,
	 *             Bitsdatos,Bitsparada,Paridad
	 */
	// public SerialPort Abrirpuerto(String nombreDePuerto, String RatioBaudios,
	// String Bitsdatos, String Bitsparada, String Paridad)
	// throws Exception
	@SuppressWarnings("unused")
	public void Abrirpuerto(String nombreDePuerto, String RatioBaudios,
			String Bitsdatos, String Bitsparada, String Paridad)
			throws Exception
	{

		/**
		 * Definicion de las variables a utilizar
		 */
		/*
		 * // CommPortIdentifier portId; OutputStream outputStream; //
		 * SerialPort PUERTOCERRAR; SerialPort puertoSerie = null;
		 * CommPortIdentifier identificadorDePuerto; InputStream in; //
		 */
		identificadorDePuerto = CommPortIdentifier
				.getPortIdentifier(nombreDePuerto);

		if (identificadorDePuerto.isCurrentlyOwned()) // Si el puerto ya esta
														// abierto que de Error
		{
			System.out
					.println("Error: El Puerto solicitado ya se encuentra en uso"); // TODO:
																					// Traducir
		} else
		{

			CommPort commPort = identificadorDePuerto.open("SimpleWrite", 2000);// sino
																				// esta
																				// usado
																				// tratar
																				// de
																				// capturar
																				// y
																				// abrir

			if (commPort instanceof SerialPort)
			{
				puertoSerie = (SerialPort) commPort;

				try
				{
					outputStream = puertoSerie.getOutputStream();
				} catch (IOException e)
				{
				}

				puertoSerie.setSerialPortParams(Integer.valueOf(RatioBaudios),
						Integer.valueOf(Bitsdatos),
						Integer.valueOf(Bitsparada), Integer.valueOf(Paridad));

				// InputStream in = serialPort.getInputStream();
				in = puertoSerie.getInputStream();
				OutputStream out = puertoSerie.getOutputStream();// TODO
				// verificar si sirve de algo

				try
				{
					puertoSerie.notifyOnOutputEmpty(true);
				} catch (Exception e)

				{
					System.out.println("Error setting event notification");// TODO
																			// traducir
					System.out.println(e.toString());
					System.exit(-1);
				}

			} else
			{
				System.out
						.println("Error: Only serial ports are handled by this example.");// TODO
																							// traducir
			}
			System.out.println("puerto Abierto " + nombreDePuerto);
		}
		// return puertoSerie;

	}

	// -----------------------------------------------------------------------------------------------------------------------------

	public int[] Analizar()
	{

		// TODO Analizar porque no verifica los datos!

		/**
		 * Las 2 primeras posiciones NO se deben analizar 0 y 1 Las 2 siguientes
		 * contienen los datos que necesitamos saber!
		 */
		// String cadenaanterior=" ";

		// int Arduino = (char)BufferLectura[1] - 48; //obtengo el nro de la
		// placa que me envia
		int placa = (char) BufferLectura[2] - 48;
		int piso = 0;
		int Seleccion1 = 0;
		int Seleccion2 = 0;
		int[] PISO = new int[16];
		switch (placa)
		{
		case 1:
			piso = 0;
			break;
		case 3:
			piso = 16;
			break;
		case 5:
			piso = 32;
			break;
		case 7:
			piso = 48;
			break;
		}

		// System.out.println("TRATANDO ANALIZAR" + piso);

		for (int u = 0; u < 8; ++u)
		{
			if ((BufferLectura[3] & (1L << u)) == 0) // analizo uno de los
														// "nibbles" recibido
			{
				Seleccion1 = u + 1 + piso;
				PISO[u] = Seleccion1;
				// System.out.println("el piso " + (Seleccion1) +
				// " esta solicitado ");
				// cadenaanterior = ascensor.NewJFrame.jAreaTexto1.getText();
				// ascensor.NewJFrame.jAreaTexto1.setText(cadenaanterior+ "|" +
				// Seleccion1);
				// CadenaMedia1 = String.valueOf(Seleccion1);
			}
		}
		// System.out.println(Cadena[3]);

		for (int u = 0; u < 8; ++u)
		{
			if ((BufferLectura[4] & (1L << u)) == 0)// analizo el otro de los
													// "nibbles" recibido
			{
				Seleccion2 = u + 9 + piso;
				PISO[u + 8] = Seleccion2;
				// System.out.println("el piso " + (Seleccion2) +
				// " esta solicitado ");
				// cadenaanterior = ascensor.NewJFrame.jAreaTexto1.getText();
				// ascensor.NewJFrame.jAreaTexto1.setText(cadenaanterior+ "|" +
				// Seleccion2);
				// CadenaMedia2 = String.valueOf(Seleccion2);
			}
		}// */

		// vacio el buffer de datos recibidos!
		for (int data = 0; data <= largoborrar; ++data)
		{
			BufferLectura[data] = 0;

		}
		// CadenaDevolver = CadenaMedia1 + CadenaMedia2;
		// return CadenaDevolver;
		return PISO; // Devuelvo en forma de vector los posibles pisos

	}

	// -----------------------------------------------------------------------------------------------------------------------------
	/**
	 * 
	 * @param nombreDePuerto
	 * @throws Exception
	 */

	// public void CerrarPuerto(String nombreDePuerto, SerialPort puerto) throws
	// Exception
	public void CerrarPuerto() throws Exception
	{
		/*
		 * OutputStream outputStream; SerialPort puertoCerrar;
		 * CommPortIdentifier identificadorDePuerto; InputStream in;
		 * 
		 * identificadorDePuerto = CommPortIdentifier
		 * .getPortIdentifier(nombreDePuerto); //
		 */
		puertoCerrar = puertoSerie;
		System.out.println("Tratando de cerrar el puerto");

		if (identificadorDePuerto.getPortType() == CommPortIdentifier.PORT_SERIAL)
		{
			System.out.println("Cerrando Puerto "
					+ identificadorDePuerto.getName());
			// puertoCerrar = puerto;
			try
			{
				outputStream = puertoCerrar.getOutputStream();
			} catch (IOException e)
			{
				System.out.println("ERROR");// TODO Traducir
			}
			try
			{
				puertoCerrar.notifyOnOutputEmpty(true);
			} catch (Exception e)
			{
				System.out.println("Error setting event notification");// TODO
																		// Traducir
				System.out.println(e.toString());
				System.exit(-1);
			}
			try
			{
				Thread.sleep(2000); // Be sure data is xferred before closing
			} catch (Exception e)
			{
			}

			puertoCerrar.close();// */
			System.out.println("Puerto Cerrado");
			// System.exit(1);

		}

	}

	// -----------------------------------------------------------------------------------------------------------------------------
	private void readSerial()
	{
		len = 0;
		int data = 0;
		PuertosDetectados = 0;
		try
		{
			int availableBytes = in.available();

			if (availableBytes > 0)
			{

				while ((data = in.read()) > 1)
				{
					if (data == '\n')
					{
						break;
					}
					BufferLectura[len++] = data;
					//System.out.println(data);
				}
				/**
				 * si llegan datos de lectura del puerto
				 */
				largoborrar = len;
				if (BufferLectura[0] == 'R') // si el primer valor recibido
												// indica que es una lectura de
												// puerto
				{
					PuertosDetectados = BufferLectura[1] - 48; // aca tengo el
																// valor
																// recibido de
																// la
																// contestacion
																// del Arduino

				}// */

				if (BufferLectura[0] == 'L') // si el primer valor recibido
												// indica que es una lectura de
												// puerto
				{
					// System.out.println("LLEGO DATO");
					largoborrar = len;
					DatosRecibidos = true;

				}// */
				if (BufferLectura[0] == 'P') // si el primer valor recibido
				// indica que es una lectura de
				// puerto
				{
					DatosRecibidos = false; 
				
					System.out.println("Ard " + (BufferLectura[1]));
					System.out.println("Sal " + (BufferLectura[2]));
					System.out.println("otro " + (BufferLectura[3]));
				
					for (int u = 0; u <= largoborrar; ++u) //vacio el dato recibido para que no me interfiera con lo demas
					{
						
						BufferLectura[u] = 0;
					}
					largoborrar = 0;
					len = 0;//*/
					//System.out.println("Ard" + BufferLectura[1]);

				}// */

			}
		} catch (IOException e)
		{
		}
	}
//-------------------------------------------------------------------------------------------------------------------------------
	/**
	 * 
	 * @return

	 * 
	 *         getter de La direccion detecta.
	 */
	public int getDireccionDetectada() 
	{
		int temporal = PuertosDetectados;
		PuertosDetectados = 0;
		return temporal;
	}

	/**
	 * 
	 * @author laboratorio Esto es para implementar como un THREAD
	 */
	/*
	 * 
	 * private class ReadThread implements Runnable { public void run() { while
	 * (true) { readSerial(); } } }
	 * 
	 * public void setSerialListener() { new Thread(new ReadThread()).start(); }
	 * //
	 */

	/**
	 * Esto es para implementar como un evento
	 * 
	 */

	private class SerialEventHandler implements SerialPortEventListener
	{
		public void serialEvent(SerialPortEvent event)
		{
			switch (event.getEventType())
			{
			case SerialPortEvent.DATA_AVAILABLE:
				readSerial();
				break;
			}
		}
	}

	/**
	 * Set the serial event handler
	 */
	private void setSerialEventHandler(SerialPort serialPort1)
	{
		try
		{
			// Add the serial port event listener
			serialPort1.addEventListener(new SerialEventHandler());
			serialPort1.notifyOnDataAvailable(true);
		} catch (TooManyListenersException ex)
		{
			System.err.println(ex.getMessage());
		}
	}

	// -----------------------------------------------------------------------------------------------------------------------------
	/**
	 * Funcion que escribe una cadena en el puerto
	 * 
	 * 
	 */
	public void EscribirPuerto(String messageString)
	{
		System.out.println("valor escrito" + messageString);
		try
		{
			outputStream.write(messageString.getBytes());
		} catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	// -----------------------------------------------------------------------------------------------------------------------------
	/**
	 * Funcion para la lectura del puerto!
	 * 
	 * @return
	 */
	public void LeerPuerto(int Puerto)
	{
		this.EscribirPuerto("OPX" + Puerto);
		// readSerial();
	}

	// -----------------------------------------------------------------------------------------------------------------------------
	public void main()
	{
		this.setSerialEventHandler(puertoSerie); //TODO: sacar de aca

	}

}
